﻿using System.ComponentModel;
using System.Net;
using System.Globalization;
using System.Reflection.Metadata;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;

namespace UMC.ITME
{

    public class SiteConfig
    {
        class UMCUri : Uri
        {
            public UMCUri([StringSyntax("Uri")] string uriString) : base(uriString)
            {
                isPort = uriString.IndexOf(":", 7) > -1;
            }
            bool isPort;
            public string UMCAuthority
            {
                get
                {
                    if (isPort)
                    {
                        return $"{this.Host}:{this.Port}";

                    }
                    else
                    {
                        return this.Authority;
                    }
                }

            }
        }
        public enum HostReplaceModel
        {
            Replace = 1,
            // Remove = 2,
            Input = 4,
            CDN = 8,
            Script = 16
        }
        public class ReplaceSetting
        {
            public HostReplaceModel Model
            {
                get;
                set;
            }

            HashSet<HostConvert> _Domains = new HashSet<HostConvert>(new EqualityComparer());
            public HashSet<HostConvert> Domains
            {
                get
                {
                    return _Domains;
                }
            }
        }
        public class LogSetting
        {
            public String[] Cookies
            {
                get;
                set;
            }
            public String[] Headers
            {
                get;
                set;
            }
            public string[] ResHeaders
            {
                get;
                set;
            }
        }
        public class TestUrl
        {
            public String[] Users
            {
                get;
                set;
            }
            public String[] Auths
            {
                get;
                set;
            }
            public string Url
            {

                get;
                set;
            }
        }
        public class HostConvert
        {
            public byte[][] Hosts = new byte[4][];
        }
        class EqualityComparer : IEqualityComparer<HostConvert>
        {

            public bool Equals(HostConvert x, HostConvert y)
            {
                return x.Hosts[0].Length == y.Hosts[0].Length && Utility.FindIndex(x.Hosts[0], 0, x.Hosts[0].Length, y.Hosts[0]) == 0;// Utility.IntParse(System.Security.Cryptography.MD5.HashData(x.Main)) == Utility.IntParse(System.Security.Cryptography.MD5.HashData(y.Main));

            }

            public int GetHashCode(HostConvert obj)
            {
                if (obj.Hosts[0].Length >= 4)
                {
                    int v = BitConverter.ToInt32(obj.Hosts[0]);
                    for (var i = 4; i < obj.Hosts[0].Length; i++)
                    {
                        v = v ^ obj.Hosts[0][i];
                    }
                    return v;
                }
                else
                {
                    var b = new byte[4];
                    Array.Copy(obj.Hosts[0], 0, b, 4 - obj.Hosts[0].Length, obj.Hosts[0].Length);
                    return BitConverter.ToInt32(b);
                }
            }
        }
        public class KeyValue
        {

            public string Key
            {

                get;
                set;
            }
            public string Value
            {

                get;
                set;
            }
            public bool IsDel
            {
                get; set;
            }
        }

        public int WeightTotal
        {
            get;
            private set;
        }
        public int[] Weights
        {
            get;
            private set;
        }
        public string Caption
        {
            get; private set;
        }
        public bool IsFile
        {

            get; private set;
        }

        public SiteConfig() { }
        public SiteConfig(Entities.Site site)
        {
            this.Caption = site.Caption;

            if (String.IsNullOrEmpty(site.Home) == false)
            {
                this.Home = site.Home;
            }

            this.Root = site.Root;
            this.Site = site;
            this.PrefixHost = new Dictionary<string, string>();

            var dom = site.Domain.Split(',', '\n');
            List<string> domains = new List<string>();
            var ls = new List<int>();
            var total = 0;
            var test = new Dictionary<String, TestUrl>();
            for (var i = 0; i < dom.Length; i++)
            {
                var v = dom[i].Trim();
                if (String.IsNullOrEmpty(v) == false)
                {
                    var valueIndex = v.IndexOf('~');
                    if (valueIndex > 0)
                    {
                        var KeepAlive = v.Substring(valueIndex + 1).Trim();
                        v = v.Substring(0, valueIndex).Trim();

                        var tIndex = v.LastIndexOf("/");
                        try
                        {
                            var kUrl = new Uri(tIndex > 8 ? v.Substring(0, tIndex) : v);
                            switch (KeepAlive)
                            {
                                case "ip4":
                                    Net.NetProxy.DNS(kUrl.Host, System.Net.Sockets.AddressFamily.InterNetwork);
                                    break;
                                case "ip6":
                                    Net.NetProxy.DNS(kUrl.Host, System.Net.Sockets.AddressFamily.InterNetworkV6);
                                    break;
                                default:
                                    Net.NetProxy.KeepAlives(kUrl, Utility.IntParse(KeepAlive, 60));
                                    break;
                            }
                        }
                        catch
                        {
                            continue;
                        }
                    }
                    if (v.StartsWith("dns://"))
                    {
                        var ds = v.Substring(6).Trim('/').Split('/');
                        switch (ds.Length)
                        {
                            case 1:
                                if (System.Text.RegularExpressions.Regex.IsMatch(ds[0], "^[a-z0-9]{1,61}\\.[a-z]{2,6}$"))
                                {
                                    Net.NetProxy.HttpDNS(ds[0]);
                                }
                                break;
                            case 2:
                                if (IPAddress.TryParse(ds[1], out var address))
                                {
                                    Net.NetProxy.DNS(ds[0], address);
                                }
                                break;
                        }
                        continue;
                    }
                    else if (v.StartsWith("http://") || v.StartsWith("https://") || v.StartsWith("file://") || v.StartsWith("unix://"))
                    {
                        if (v.EndsWith("]"))
                        {
                            var tUrl = v;

                            var vin = v.LastIndexOf("[");
                            if (vin > -1)
                            {
                                ls.Add(UMC.Data.Utility.IntParse(v.Substring(vin + 1).Trim(']', '[').Trim(), 1));

                                total += ls[ls.Count - 1];
                                tUrl = v.Substring(0, vin).TrimEnd(']', ' ').Trim();
                            }
                            else
                            {
                                total++;
                                ls.Add(1);
                            }

                            var sIndex = tUrl.IndexOf('/', 8);
                            if (sIndex > 0)
                            {
                                tUrl = tUrl.Substring(0, sIndex);
                            }
                            domains.Add(tUrl);

                        }
                        else
                        {
                            var tIndex = v.IndexOf('@');
                            var tUrl = v;
                            if (tIndex > 0)
                            {
                                tUrl = v.Substring(0, tIndex);
                                var uvs = v.Substring(tIndex + 1).Split(',', ' ');
                                var tUsers = new List<String>();
                                var tAuth = new List<String>();
                                foreach (var uv in uvs)
                                {
                                    var uname = uv.Trim();
                                    if (String.IsNullOrEmpty(uname) == false)
                                    {
                                        if (uname.IndexOf('/') == -1)
                                        {
                                            tUsers.Add(uname);
                                        }
                                        else
                                        {
                                            tAuth.Add(uname);
                                        }
                                    }
                                }
                                if (tUsers.Count > 0 || tAuth.Count > 0)
                                {
                                    var sIndex = tUrl.IndexOf('/', 8);//, tIndex);
                                    if (sIndex > 0)
                                    {
                                        tUrl = tUrl.Substring(0, sIndex);
                                    }

                                    test[tUrl.Trim()] = new TestUrl { Auths = tAuth.ToArray(), Users = tUsers.ToArray(), Url = tUrl };
                                }
                            }
                            else
                            {
                                if (tUrl.StartsWith("file://") == false)
                                {
                                    var sIndex = tUrl.IndexOf('/', 8);
                                    if (sIndex > 0)
                                    {
                                        tUrl = tUrl.Substring(0, sIndex);
                                    }
                                }
                                domains.Add(tUrl);
                                total++;
                                ls.Add(1);
                            }

                        }
                    }
                    else if (v.Contains('.'))
                    {
                        this.PrefixHost[v.Replace('.', '-')] = v;
                    }
                }

                if (domains.Count > 0)
                {
                    if (IsFile == false)
                    {
                        var url = domains.Last();
                        IsFile = url.StartsWith("file://", StringComparison.CurrentCultureIgnoreCase);
                        if (IsFile)
                        {
                            domains.Clear();
                            domains.Add(url);
                            break;
                        }
                    }
                }
            }
            this.Domains = domains.ToArray();
            this._test = test.Values.ToArray();

            this.WeightTotal = total;
            this.Weights = ls.ToArray();

            this.LogoutPath = Config(site.LogoutPath);
            this.AppendJSConf = Config(site.AppendJSConf);
            this.RedirectPath = Config(site.RedirectPath);
            this.ImagesConf = Config(site.ImagesConf);
            this.ConfigAllowPath(site.AuthConf);
            var subSite = new List<KeyValue>();
            if (String.IsNullOrEmpty(site.SubSite) == false)
            {
                var v = UMC.Data.JSON.Deserialize(site.SubSite) as Hashtable;
                if (v != null)
                {
                    var pem = v.GetEnumerator();
                    while (pem.MoveNext())
                    {
                        var key = pem.Key as string;
                        if (key.EndsWith("*"))
                        {
                            subSite.Add(new KeyValue { Key = key.Substring(0, key.Length - 1), Value = pem.Value.ToString(), IsDel = true });
                        }
                        else
                        {
                            subSite.Add(new KeyValue { Key = key, Value = pem.Value.ToString() });
                        }

                    }
                }
            }
            _subSite = subSite.ToArray();
            InitStatic(site.StaticConf);
            InitHeader(site.HeaderConf);
            InitLogConf(site.LogConf);

            InitCookie(site.OutputCookies);

            InitHost(site.HostReConf);

        }
        public bool AllowAllPath
        {
            get; set;
        }

        /// <summary>
        /// 默认ContentType类型
        /// </summary>
        public string ContentType
        {
            get; set;
        }
        public static bool CheckMime(Hashtable login)
        {
            var rawUrl = login["RawUrl"] as string;
            if (String.IsNullOrEmpty(rawUrl))
            {
                return false;

            }


            var Method = login["Method"] as string;
            if (String.IsNullOrEmpty(Method))
            {
                return false;
            }

            switch (Method)
            {
                case "POST":
                case "PUT":
                    var ContentType = login["ContentType"] as string;
                    if (String.IsNullOrEmpty(ContentType))
                    {
                        return false;
                    }
                    var value = login["Content"] as string;
                    if (String.IsNullOrEmpty(value))
                    {
                        return false;
                    }
                    break;
            }
            var Finish = login["Finish"] as string;
            if (String.IsNullOrEmpty(Finish))
            {
                return false;
            }
            return true;
        }
        void InitLogConf(String sConf)
        {

            this.LogConf = new LogSetting();

            var cs = new List<String>();
            var hs = new List<String>();
            var rhs = new List<String>();
            if (String.IsNullOrEmpty(sConf) == false)
            {
                foreach (var k in sConf.Split('\n', ','))
                {

                    var v = k.Trim();
                    if (String.IsNullOrEmpty(v) == false && String.Equals(k, "none") == false)
                    {
                        if (v.StartsWith(":"))
                        {
                            hs.Add(v.Substring(1));
                        }
                        else if (v.EndsWith(":"))
                        {

                            rhs.Add(v.Substring(0, v.Length - 1));
                        }
                        else
                        {
                            cs.Add(v);
                        }
                    }

                }
            }

            this.LogConf.Headers = hs.ToArray();
            this.LogConf.ResHeaders = rhs.ToArray();
            this.LogConf.Cookies = cs.ToArray();
        }
        void InitCookie(String sConf)
        {

            if (String.IsNullOrEmpty(sConf) == false)
            {

                foreach (var k in sConf.Split('\n', ','))
                {

                    var v = k.Trim();
                    if (String.IsNullOrEmpty(v) == false && String.Equals(k, "none") == false)
                    {
                        var nindex = -1;
                        for (int i = 0; i < v.Length; i++)
                        {
                            if (v[i] == ' ' || v[i] == '\t' || v[i] == ':')
                            {
                                nindex = i;
                                break;
                            }
                        }

                        if (nindex > -1)
                        {
                            var vs = _OutputCookies;
                            var mv = v.Substring(nindex + 1).Trim();
                            var key = v.Substring(0, nindex).Trim();
                            var kIndex = mv.IndexOf(':');
                            if (kIndex > 0)
                            {
                                if (_SubsOutputCookies.TryGetValue(key, out vs) == false)
                                {
                                    vs = new Dictionary<string, string>();
                                    _SubsOutputCookies[key] = vs;
                                }
                                key = mv.Substring(0, kIndex);
                                mv = mv.Substring(kIndex + 1).Trim();
                            }
                            if (mv.StartsWith('/'))
                            {
                                vs[key] = mv;
                            }
                        }

                    }

                }
            }
        }
        void InitHeader(String sConf)
        {

            if (String.IsNullOrEmpty(sConf) == false)
            {

                foreach (var k in sConf.Split('\n', ','))
                {

                    var v = k.Trim();
                    if (String.IsNullOrEmpty(v) == false && String.Equals(v, "none") == false)
                    {

                        var nindex = -1;
                        for (int i = 0; i < v.Length; i++)
                        {
                            if (v[i] == ' ' || v[i] == '\t' || v[i] == ':')
                            {
                                nindex = i;
                                break;
                            }
                        }

                        if (nindex > -1)
                        {
                            var mv = v.Substring(nindex + 1).Trim();
                            var key = v.Substring(0, nindex).Trim();
                            if (String.IsNullOrEmpty(mv) == false && String.IsNullOrEmpty(key) == false)
                            {
                                switch (key.ToLower())
                                {
                                    case "content-type":
                                        this.ContentType = mv;
                                        break;
                                    default:
                                        _HeaderConf[key] = mv;
                                        break;
                                }
                            }

                        }
                    }

                }

            }
        }

        void InitStatic(String sConf)
        {
            var stateValues = new List<PageConfig<int>>();
            if (String.IsNullOrEmpty(sConf) == false)
            {
                foreach (var k in sConf.Split('\n', ','))
                {

                    var v = k.Trim();
                    if (String.IsNullOrEmpty(v) == false && String.Equals(v, "none") == false)
                    {

                        var nindex = -1;
                        for (int i = 0; i < v.Length; i++)
                        {
                            if (v[i] == ' ' || v[i] == '\t' || v[i] == ':')
                            {
                                nindex = i;
                                break;
                            }
                        }
                        var page = new PageConfig<int>() { StartPath = String.Empty, EndPath = String.Empty };
                        page.Value = -1;
                        var key = v;
                        if (nindex > -1)
                        {
                            var mv = v.Substring(nindex + 1).Trim().ToLower();
                            key = v.Substring(0, nindex).Trim();
                            var splitIndex = key.IndexOf('*');
                            switch (splitIndex)
                            {
                                case -1:
                                    page.StartPath = key;
                                    break;
                                case 0:
                                    if (key.Length > 1)
                                    {
                                        page.EndPath = key.Substring(1);
                                    }
                                    else
                                    {
                                        continue;
                                    }

                                    break;
                                default:
                                    if (splitIndex == key.Length - 1)
                                    {
                                        page.StartPath = key.Substring(0, key.Length - 1);
                                    }
                                    else
                                    {
                                        page.StartPath = key.Substring(0, splitIndex);
                                        page.EndPath = key.Substring(splitIndex + 1);

                                    }

                                    break;

                            }
                            switch (mv)
                            {
                                case "a":
                                case "all":
                                    page.Value = 0;
                                    break;
                                case "u":
                                case "user":
                                    page.Value = 2;
                                    break;
                                case "one":
                                    page.Value = 3;
                                    break;
                                default:
                                    page.Value = UMC.Data.Utility.IntParse(mv, -1);
                                    break;
                            }
                        }
                        else
                        {
                            page.StartPath = key;
                        }
                        stateValues.Add(page);
                    }

                }

            }
            _StatusPage = stateValues.ToArray();
        }
        public HostConvert MainHost
        {
            get;
            private set;
        }
        public bool IsUnion
        {
            get;
            private set;
        }

        public HostConvert SuffixHost
        {
            get;
            private set;
        }
        public Dictionary<String, String> PrefixHost
        {
            get; private set;
        }

        void InitHost(String sConf)
        {
            // this.PrefixHost = new Dictionary<string, string>();
            var domain = UMC.ITME.WebServlet.MainDomain;
            var union = UMC.ITME.WebServlet.DomainUnion;
            if (this.Domains.Length > 0)
            {
                var url = this.Domains[0];
                var hostConvert = this.MainHost = new HostConvert();
                int sufx = 1;
                if (url.Contains('*'))
                {
                    IsUnion = true;
                    hostConvert.Hosts[0] = System.Text.ASCIIEncoding.UTF8.GetBytes($"-{this.Site.Root}{union}{domain}");
                    var l = new UMCUri(url.Replace("*.", ""));
                    hostConvert.Hosts[1] = System.Text.ASCIIEncoding.UTF8.GetBytes('.' + l.Host);
                    hostConvert.Hosts[2] = System.Text.ASCIIEncoding.UTF8.GetBytes('.' + l.UMCAuthority);
                    hostConvert.Hosts[3] = System.Text.ASCIIEncoding.UTF8.GetBytes(Uri.EscapeDataString('.' + l.UMCAuthority));

                }
                else
                {

                    if (String.IsNullOrEmpty(this.Site.Host) == false)
                    {
                        url = url.Replace(new UMCUri(url).Host, this.Site.Host);
                    }
                    hostConvert.Hosts[0] = System.Text.ASCIIEncoding.UTF8.GetBytes($"{this.Site.Root}{union}{domain}");
                    var l = new UMCUri(url);
                    sufx = l.Host.IndexOf('.');
                    hostConvert.Hosts[1] = System.Text.ASCIIEncoding.UTF8.GetBytes(l.Host);
                    hostConvert.Hosts[2] = System.Text.ASCIIEncoding.UTF8.GetBytes(l.UMCAuthority);
                    hostConvert.Hosts[3] = System.Text.ASCIIEncoding.UTF8.GetBytes(Uri.EscapeDataString(l.UMCAuthority));


                }
                var suffixHost = new HostConvert();
                if (union == '-')
                {
                    suffixHost.Hosts[0] = System.Text.ASCIIEncoding.UTF8.GetBytes(domain.Substring(domain.IndexOf('.') + 1));
                }
                else
                {
                    suffixHost.Hosts[0] = System.Text.ASCIIEncoding.UTF8.GetBytes(domain);
                }
                if (this.IsFile == false)
                {
                    suffixHost.Hosts[1] = this.MainHost.Hosts[1].AsSpan(sufx, this.MainHost.Hosts[1].Length - sufx).ToArray();// System.Text.ASCIIEncoding.UTF8.GetBytes(String.Format(".{0}{1}{2}", this.Site.Root, union, domain));
                    suffixHost.Hosts[2] = this.MainHost.Hosts[2].AsSpan(sufx, this.MainHost.Hosts[2].Length - sufx).ToArray();// System.Text.ASCIIEncoding.UTF8.GetBytes(String.Format(".{0}{1}{2}", this.Site.Root, union, domain));
                    suffixHost.Hosts[3] = this.MainHost.Hosts[3].AsSpan(sufx, this.MainHost.Hosts[3].Length - sufx).ToArray();// System.Text.ASCIIEncoding.UTF8.GetBytes(String.Format(".{0}{1}{2}", this.Site.Root, union, domain));
                }
                this.SuffixHost = suffixHost;

            }
            var hostPage = new HashSet<PageConfig<ReplaceSetting>>(new EqualityComparer<ReplaceSetting>());
            // hostPage.TryGetValue
            if (String.IsNullOrEmpty(sConf) == false)
            {
                foreach (var k in sConf.Split('\n'))
                {

                    var v = k.Trim();
                    if (String.IsNullOrEmpty(v) == false && String.Equals(v, "none") == false)
                    {

                        var nindex = -1;
                        for (int i = 0; i < v.Length; i++)
                        {
                            if (v[i] == ' ' || v[i] == '\t' || v[i] == ':')
                            {
                                nindex = i;
                                break;
                            }
                        }
                        var key = v;
                        if (nindex > -1)
                        {
                            var mv = v.Substring(nindex + 1).Split(',', ' ', '\t');
                            key = v.Substring(0, nindex).Trim();

                            var page = new PageConfig<ReplaceSetting>() { StartPath = String.Empty, EndPath = String.Empty };

                            var splitIndex = key.IndexOf('*');
                            switch (splitIndex)
                            {
                                case -1:
                                    page.StartPath = key;
                                    break;
                                case 0:
                                    if (key.Length > 1)
                                    {
                                        page.EndPath = key.Substring(1);
                                    }
                                    else
                                    {
                                        continue;
                                    }

                                    break;
                                default:
                                    if (splitIndex == key.Length - 1)
                                    {
                                        page.StartPath = key.Substring(0, key.Length - 1);
                                    }
                                    else
                                    {
                                        page.StartPath = key.Substring(0, splitIndex);
                                        page.EndPath = key.Substring(splitIndex + 1);

                                    }

                                    break;

                            }

                            if (hostPage.TryGetValue(page, out var _page) == false)
                            {
                                page.Value = new ReplaceSetting() { Model = HostReplaceModel.Replace };
                                _page = page;
                                hostPage.Add(page);

                            }
                            ReplaceSetting replaceSetting = _page.Value;//[key];
                            HostReplaceModel hostReplace = replaceSetting.Model;
                            var list = replaceSetting.Domains;

                            foreach (var kv in mv)
                            {
                                var vk = kv.Trim();
                                if (String.IsNullOrEmpty(vk) == false)
                                {

                                    switch (vk)
                                    {
                                        case ".":
                                            if (this.IsUnion || union == '-')
                                            {

                                                var hostConvert = new HostConvert();
                                                if (union == '-')
                                                {
                                                    hostConvert.Hosts[0] = System.Text.ASCIIEncoding.UTF8.GetBytes(domain.Substring(domain.IndexOf('.') + 1));
                                                }
                                                else
                                                {
                                                    hostConvert.Hosts[0] = System.Text.ASCIIEncoding.UTF8.GetBytes(domain);
                                                }
                                                hostConvert.Hosts[1] = this.MainHost.Hosts[1].AsSpan(1, this.MainHost.Hosts[1].Length - 1).ToArray();// System.Text.ASCIIEncoding.UTF8.GetBytes(String.Format(".{0}{1}{2}", this.Site.Root, union, domain));
                                                hostConvert.Hosts[2] = this.MainHost.Hosts[2].AsSpan(1, this.MainHost.Hosts[2].Length - 1).ToArray();// System.Text.ASCIIEncoding.UTF8.GetBytes(String.Format(".{0}{1}{2}", this.Site.Root, union, domain));
                                                hostConvert.Hosts[3] = this.MainHost.Hosts[3].AsSpan(1, this.MainHost.Hosts[3].Length - 1).ToArray();// System.Text.ASCIIEncoding.UTF8.GetBytes(String.Format(".{0}{1}{2}", this.Site.Root, union, domain));
                                                list.Add(hostConvert);

                                            }
                                            break;
                                        default:
                                            var vIndex = vk.IndexOf(':');
                                            if (vIndex > 0)
                                            {
                                                var hostConvert = new HostConvert();

                                                var hMain = vk.Substring(0, vIndex).Trim();
                                                var proxy = vk.Substring(vIndex + 1).Trim();
                                                if (hMain.EndsWith("."))
                                                {
                                                    if (String.IsNullOrEmpty(proxy) == false && proxy.Contains('.') == false)
                                                    {
                                                        var vl = hMain.Replace('.', '-');
                                                        var sit = DataFactory.Instance().Site(proxy);
                                                        if (sit != null)
                                                        {
                                                            var doms = sit.Domain.Split(',', '\n');
                                                            foreach (var dName in doms)
                                                            {
                                                                var dName2 = dName.Trim();
                                                                var url = String.Empty;
                                                                if (String.IsNullOrEmpty(dName2) == false)
                                                                {
                                                                    var tIndex = dName2.IndexOf('~');
                                                                    if (tIndex > 0)
                                                                    {
                                                                        dName2 = dName2.Substring(0, tIndex).Trim();
                                                                    }

                                                                    if (dName2.EndsWith("]"))
                                                                    {
                                                                        var vin = dName2.LastIndexOf("[");
                                                                        if (vin > -1)
                                                                        {
                                                                            url = dName2.Substring(0, vin).TrimEnd(']', ' ').Trim();
                                                                        }
                                                                        else
                                                                        {
                                                                            url = dName2.Substring(0, vin).TrimEnd(']', ' ').Trim();
                                                                        }
                                                                        var sIndex = url.LastIndexOf('/');
                                                                        if (sIndex > 0)
                                                                        {

                                                                            url = url.Substring(0, sIndex);
                                                                        }
                                                                    }
                                                                    else if (v.IndexOf('@') == -1)
                                                                    {
                                                                        url = dName2;
                                                                        var sIndex = url.LastIndexOf('/');
                                                                        if (sIndex > 0)
                                                                        {
                                                                            url = url.Substring(0, sIndex);
                                                                        }

                                                                    }
                                                                }
                                                                if (String.IsNullOrEmpty(url) == false)
                                                                {
                                                                    if (url.Contains('*'))
                                                                    {
                                                                        hostConvert.Hosts[0] = System.Text.ASCIIEncoding.UTF8.GetBytes($"{vl}{sit.Root}{union}{domain}");
                                                                        var l = new UMCUri(url.Replace("*.", ""));
                                                                        hostConvert.Hosts[1] = System.Text.ASCIIEncoding.UTF8.GetBytes(hMain + l.Host);
                                                                        hostConvert.Hosts[2] = System.Text.ASCIIEncoding.UTF8.GetBytes(hMain + l.UMCAuthority);
                                                                        hostConvert.Hosts[3] = System.Text.ASCIIEncoding.UTF8.GetBytes(Uri.EscapeDataString(hMain + l.UMCAuthority));

                                                                        list.Add(hostConvert);
                                                                        break;
                                                                    }
                                                                }
                                                            }
                                                        }

                                                        break;
                                                    }
                                                }
                                                else if (String.Equals(hMain, "-"))
                                                {
                                                    hMain = $"{this.Site.Root}{union}{domain}";
                                                }
                                                hostConvert.Hosts[0] = System.Text.ASCIIEncoding.UTF8.GetBytes(hMain);

                                                if (String.IsNullOrEmpty(proxy) == false)
                                                {
                                                    var pIndex = proxy.IndexOf(':');
                                                    if (pIndex > 0)
                                                    {
                                                        hostConvert.Hosts[1] = System.Text.ASCIIEncoding.UTF8.GetBytes(proxy.Substring(0, pIndex));
                                                        hostConvert.Hosts[2] = System.Text.ASCIIEncoding.UTF8.GetBytes(proxy);

                                                    }
                                                    else
                                                    {
                                                        hostConvert.Hosts[1] =
                                                        hostConvert.Hosts[2] = System.Text.ASCIIEncoding.UTF8.GetBytes(proxy);

                                                    }
                                                    hostConvert.Hosts[3] = System.Text.ASCIIEncoding.UTF8.GetBytes(Uri.EscapeDataString(proxy));

                                                    list.Add(hostConvert);
                                                }
                                            }
                                            else if (vk.EndsWith("."))
                                            {
                                                if (this.IsUnion)
                                                {
                                                    var vsrc = vk.Substring(0, vk.Length - 1);
                                                    var vv = vsrc.Replace('.', '-');
                                                    PrefixHost[vv] = vsrc;//vk.Replace('.', '-');

                                                    var vkb = System.Text.ASCIIEncoding.UTF8.GetBytes(vv);
                                                    var vhm = new byte[vkb.Length + this.MainHost.Hosts[0].Length];
                                                    Array.Copy(vkb, 0, vhm, 0, vkb.Length);
                                                    Array.Copy(this.MainHost.Hosts[0], 0, vhm, vkb.Length, this.MainHost.Hosts[0].Length);
                                                    var hostConvert = new HostConvert();
                                                    hostConvert.Hosts[0] = vhm;

                                                    var vsrcb = System.Text.ASCIIEncoding.UTF8.GetBytes(vsrc);
                                                    for (var i = 1; i <= 3; i++)
                                                    {
                                                        var vhm1 = new byte[vkb.Length + this.MainHost.Hosts[i].Length];

                                                        Array.Copy(vsrcb, 0, vhm1, 0, vsrcb.Length);

                                                        Array.Copy(this.MainHost.Hosts[i], 0, vhm1, vsrcb.Length, this.MainHost.Hosts[i].Length);

                                                        hostConvert.Hosts[i] = vhm1;
                                                    }
                                                    list.Add(hostConvert);

                                                }

                                            }
                                            else
                                            {
                                                var sit = DataFactory.Instance().Site(vk);
                                                if (sit != null)
                                                {
                                                    var doms = sit.Domain.Split(',', '\n');
                                                    foreach (var dName in doms)
                                                    {
                                                        var dName2 = dName.Trim();
                                                        var url = String.Empty;
                                                        if (String.IsNullOrEmpty(dName2) == false)
                                                        {
                                                            var tIndex = dName2.IndexOf('~');
                                                            if (tIndex > 0)
                                                            {
                                                                dName2 = dName2.Substring(0, tIndex).Trim();
                                                            }

                                                            if (dName2.EndsWith("]"))
                                                            {
                                                                var vin = dName2.LastIndexOf("[");
                                                                if (vin > -1)
                                                                {
                                                                    url = dName2.Substring(0, vin).TrimEnd(']', ' ').Trim();
                                                                }
                                                                else
                                                                {
                                                                    url = dName2.Substring(0, vin).TrimEnd(']', ' ').Trim();
                                                                }
                                                                var sIndex = url.LastIndexOf('/');
                                                                if (sIndex > 0)
                                                                {

                                                                    url = url.Substring(0, sIndex);
                                                                }
                                                            }
                                                            else if (v.IndexOf('@') == -1)
                                                            {
                                                                url = dName2;
                                                                var sIndex = url.LastIndexOf('/');
                                                                if (sIndex > 0)
                                                                {
                                                                    url = url.Substring(0, sIndex);
                                                                }

                                                            }
                                                        }
                                                        if (String.IsNullOrEmpty(url) == false)
                                                        {
                                                            var hostConvert = new HostConvert();

                                                            if (url.Contains('*'))
                                                            {
                                                                hostConvert.Hosts[0] = System.Text.ASCIIEncoding.UTF8.GetBytes($"-{sit.Root}{union}{domain}");
                                                                var l = new UMCUri(url.Replace("*.", ""));
                                                                hostConvert.Hosts[1] = System.Text.ASCIIEncoding.UTF8.GetBytes('.' + l.Host);
                                                                hostConvert.Hosts[2] = System.Text.ASCIIEncoding.UTF8.GetBytes('.' + l.UMCAuthority);
                                                                hostConvert.Hosts[3] = System.Text.ASCIIEncoding.UTF8.GetBytes(Uri.EscapeDataString('.' + l.UMCAuthority));
                                                            }
                                                            else
                                                            {
                                                                if (String.IsNullOrEmpty(sit.Host) == false)
                                                                {
                                                                    url = url.Replace(new UMCUri(url).Host, sit.Host);
                                                                }
                                                                hostConvert.Hosts[0] = System.Text.ASCIIEncoding.UTF8.GetBytes($"{sit.Root}{union}{domain}");
                                                                var l = new UMCUri(url);
                                                                hostConvert.Hosts[1] = System.Text.ASCIIEncoding.UTF8.GetBytes(l.Host);
                                                                hostConvert.Hosts[2] = System.Text.ASCIIEncoding.UTF8.GetBytes(l.UMCAuthority);
                                                                hostConvert.Hosts[3] = System.Text.ASCIIEncoding.UTF8.GetBytes(Uri.EscapeDataString(l.UMCAuthority));


                                                            }
                                                            list.Add(hostConvert);
                                                            break;
                                                        }
                                                    }
                                                }
                                            }
                                            break;
                                        case "rp":
                                            hostReplace |= HostReplaceModel.Replace;
                                            break;
                                        case "rm":
                                            hostReplace |= HostReplaceModel.Replace;
                                            break;
                                        case "input":
                                        case "in":
                                            hostReplace |= HostReplaceModel.Input;
                                            break;
                                    }
                                }
                            }
                            replaceSetting.Model = hostReplace;

                        }
                    }
                }
            }
            _HostPage = hostPage;
        }


        public static Guid MD5Key(params object[] keys)
        {
            var md5 = System.Security.Cryptography.MD5.Create();
            return new Guid(md5.ComputeHash(System.Text.Encoding.UTF8.GetBytes(String.Join(",", keys))));


        }
        void ConfigAllowPath(String sConf)
        {

            var saticPagePath = new HashSet<PageConfig<int>>(new EqualityComparer<int>());
            Dictionary<String, HashSet<PageConfig<int>>> subs = new System.Collections.Generic.Dictionary<string, HashSet<PageConfig<int>>>();
            if (String.IsNullOrEmpty(sConf) == false)
            {

                foreach (var k in sConf.Split(',', ' ', '\t', '\n'))
                {
                    var v = k.Trim();
                    if (String.IsNullOrEmpty(v) == false && String.Equals("none", v) == false)
                    {
                        var checPath = saticPagePath;
                        var vIndex = v.IndexOf(':');
                        if (vIndex > 0)
                        {
                            var key = v.Substring(0, vIndex);
                            if (subs.TryGetValue(key, out checPath) == false)
                            {
                                checPath = new HashSet<PageConfig<int>>(new EqualityComparer<int>());
                                subs.Add(key, checPath);
                            }
                            v = v.Substring(vIndex + 1).Trim();
                        }
                        if (String.IsNullOrEmpty(v))
                        {
                            continue;
                        }
                        var page = new PageConfig<int>() { StartPath = String.Empty, EndPath = String.Empty };

                        var splitIndex = v.IndexOf('*');
                        switch (splitIndex)
                        {
                            case -1:
                                page.StartPath = v;
                                break;
                            case 0:
                                if (v.Length > 1)
                                {
                                    page.EndPath = v.Substring(1);
                                }
                                else
                                {
                                    if (vIndex == -1)
                                    {
                                        this.AllowAllPath = true;
                                    }
                                    checPath.Clear();
                                    continue;
                                }

                                break;
                            default:
                                if (splitIndex == v.Length - 1)
                                {
                                    page.StartPath = v.Substring(0, v.Length - 1);
                                }
                                else
                                {
                                    page.StartPath = v.Substring(0, splitIndex);
                                    page.EndPath = v.Substring(splitIndex + 1);

                                }

                                break;

                        }
                        checPath.Add(page);


                    }
                }
            }
            this.AllowSubsPath = new Dictionary<string, PageConfig<int>[]>();
            var em = subs.GetEnumerator();
            while (em.MoveNext())
            {
                this.AllowSubsPath.Add(em.Current.Key, em.Current.Value.ToArray());
            }
            this.AllowPath = saticPagePath.ToArray();

            this.IsClose = this.Site.Flag < 0 || this.Domains.Length == 0;
            IsCheck();
        }

        public bool IsCheck()
        {
            if (this.IsClose == false)
            {
                if (String.IsNullOrEmpty(this.Site.MarketKey) == false)
                {
                    this.IsClose = UMC.Data.License.GetLicense(this.Site.MarketKey).ExpireTime < Utility.TimeSpan();
                    return this.IsClose;
                }
            }
            return false;
        }
        public static String[] Config(String sConf)
        {
            var saticPagePath = new HashSet<String>();

            if (String.IsNullOrEmpty(sConf) == false)
            {

                foreach (var k in sConf.Split(',', ' ', '\t', '\n'))
                {

                    var v = k.Trim();
                    if (String.IsNullOrEmpty(v) == false && String.Equals("none", v) == false)
                    {
                        saticPagePath.Add(v);
                    }
                }
            }
            return saticPagePath.ToArray();
        }
        public String Home
        {
            get;
            private set;
        }
        public String Root
        {
            get; set;
        }

        public Entities.Site Site
        {
            get; private set;
        }

        public String[] Domains
        {
            get;
            private set;
        }
        public LogSetting LogConf
        {
            get;
            private set;
        }

        public PageConfig<int>[] AllowPath
        {
            get;
            private set;
        }
        public Dictionary<String, PageConfig<int>[]> AllowSubsPath
        {
            get;
            private set;
        }
        public String[] LogoutPath
        {
            get;
            private set;
        }

        System.Collections.Generic.Dictionary<String, String> _OutputCookies = new Dictionary<string, string>();
        System.Collections.Generic.Dictionary<String, Dictionary<string, String>> _SubsOutputCookies = new Dictionary<string, Dictionary<string, string>>();

        public System.Collections.Generic.Dictionary<String, String> Cookies
        {
            get
            {
                return _OutputCookies;
            }
        }
        public Dictionary<string, Dictionary<string, String>> SubCookies
        {
            get
            {
                return _SubsOutputCookies;
            }
        }
        public String[] ImagesConf
        {
            get;
            private set;
        }
        public String[] AppendJSConf
        {

            get;
            private set;
        }
        public string[] RedirectPath
        {
            get;
            private set;
        }
        public bool IsClose
        {

            get;
            private set;
        }


        public System.Collections.Generic.Dictionary<String, String> HeaderConf
        {
            get
            {
                return _HeaderConf;
            }
        }
        System.Collections.Generic.Dictionary<String, String> _HeaderConf = new Dictionary<string, String>();

        public PageConfig<int>[] StatusPage
        {
            get
            {
                return _StatusPage;
            }
        }
        public class PageConfig<T>
        {
            public string StartPath;
            public string EndPath;
            public T Value;
        }

        class EqualityComparer<T> : IEqualityComparer<PageConfig<T>>
        {

            public bool Equals(PageConfig<T> x, PageConfig<T> y)
            {
                return GetHashCode(x) == GetHashCode(y);
            }

            public int GetHashCode([DisallowNull] PageConfig<T> obj)
            {
                return obj.StartPath.GetHashCode() ^ obj.EndPath.GetHashCode();
            }
        }
        PageConfig<int>[] _StatusPage;


        TestUrl[] _test;

        public TestUrl[] Test
        {

            get
            {
                return _test;
            }
        }
        HashSet<PageConfig<ReplaceSetting>> _HostPage;
        public HashSet<PageConfig<ReplaceSetting>> HostPage
        {

            get
            {
                return _HostPage;
            }
        }

        KeyValue[] _subSite;
        public KeyValue[] SubSite
        {
            get
            {
                return _subSite;

            }
        }
    }
}
